import { isArray, isString, isObj } from '@/utils/type'
import Highlight from './highlight'
import $ from 'jquery'
import dateRange from '@/utils/dateRange'

class PageQuery {
  current = 1
  size = 50
}

class SearchQuery {
}

class SortQuery {
}

class FilterQuery {
}

// class Query {
//   constructor(Querys) {
//     return {...new PageQuery(), ...new SearchQuery(), ...new SortQuery(), ...new FilterQuery()}
//     // let obj = {}
//     // Array.prototype.forEach.call(arguments, Query => {
//     //   // console.log(Query)
//     //   obj = {...obj, ...new Query()}
//     // })
//     // return obj
//   }
// }

function generateTableData(prefixTableName, pk, parent) {
  const data = {}
  data[`${prefixTableName}RawRes`] = null
  data[`${prefixTableName}IsScrollTop`] = false
  data[`${prefixTableName}InitLoading`] = false
  data[`${prefixTableName}Loading`] = false
  data[`${prefixTableName}Complete`] = false
  data[`${prefixTableName}Summary`] = {}
  data[`${prefixTableName}CanGetMoreList`] = false
  data[`${prefixTableName}List`] = []
  data[`${prefixTableName}PageQuery`] = new PageQuery(),
  data[`${prefixTableName}SearchQuery`] = new SearchQuery(),
  data[`${prefixTableName}SortQuery`] = new SortQuery(),
  data[`${prefixTableName}FilterQuery`] = new FilterQuery(),
  data[`${prefixTableName}SelectedRow`] = null
  data[`${prefixTableName}SelectedRows`] = []
  data[`${prefixTableName}SelectedRowId`] = ''
  data[`${prefixTableName}SelectedRowIds`] = []
  data[`${prefixTableName}Adder`] = {visible: false, mode: ''}
  if (pk) {
    data[`${prefixTableName}Pk`] = pk
    data[`${prefixTableName}SelectedRowPk`] = ''
    data[`${prefixTableName}SelectedRowPks`] = []
  }
  if (parent) {
    data[`${prefixTableName}Parent`] = parent
  }
  return data
}

function generateTableMethod(prefixTableName = 'default') {
  const methods = {}
  methods[`${prefixTableName}GetInitList`] = function (moreQuery = {}) {
    this[`${prefixTableName}UnSelectRow`]()

    this[`${prefixTableName}CanGetMoreList`] = false
    this[`${prefixTableName}InitLoading`] = true
    this[`${prefixTableName}Loading`] = true
    this[`${prefixTableName}IsScrollTop`] = true

    this[`${prefixTableName}PageQuery`] = new PageQuery()
    const query = {
      params: {
        ...this.searchQuery,
        ...this[`${prefixTableName}PageQuery`],
        ...this[`${prefixTableName}SearchQuery`],
        ...this[`${prefixTableName}SortQuery`],
        ...this[`${prefixTableName}FilterQuery`],
        ...moreQuery
      }
    }
    const parentName = this[`${prefixTableName}Parent`]
    if (parentName) {
      const parentPk = this[`${parentName}Pk`]
      if (parentPk) {
        query.pid = this[`${parentName}SelectedRowPk`]
      } else {
        query.pid = this[`${parentName}SelectedRowId`]
      }
    }
    this[`${prefixTableName}ApiGetList`](query).then(res => {
      this[`${prefixTableName}InitLoading`] = false
      this[`${prefixTableName}Loading`] = false
      this[`${prefixTableName}CanGetMoreList`] = true

      const rawList = res.data.list ? res.data.list : res.data
      // console.log(this[`${prefixTableName}SearchQuery`])
      const list = new Highlight(rawList, this[`${prefixTableName}SearchQuery`]).search()
      this[`${prefixTableName}List`] = res.data.list
      this[`${prefixTableName}Summary`] = {...res.data.summary, total: res.data.total}
      // this.$nextTick(() => {
      this[`${prefixTableName}IsScrollTop`] = false
      // })
    })
  }

  methods[`${prefixTableName}GetMoreList`] = function ({scrollTop, scrollLeft, table, judgeFlse}, event) {

    if (!judgeFlse || this[`${prefixTableName}Complete`] || this[`${prefixTableName}InitLoading`] || this[`${prefixTableName}Loading`]) return

    this[`${prefixTableName}Loading`] = true
    const query = {
      params: {
        ...this.searchQuery,
        ...this[`${prefixTableName}PageQuery`], current: this[`${prefixTableName}PageQuery`].current + 1,
        ...this[`${prefixTableName}SearchQuery`],
        ...this[`${prefixTableName}SortQuery`],
        ...this[`${prefixTableName}FilterQuery`]
      }
    }
    const parentName = this[`${prefixTableName}Parent`]
    if (parentName) {
      const parentPk = this[`${parentName}Pk`]
      if (parentPk) {
        query.pid = this[`${parentName}SelectedRowPk`]
      } else {
        query.pid = this[`${parentName}SelectedRowId`]
      }
    }
    this[`${prefixTableName}ApiGetList`](query).then(res => {
      this[`${prefixTableName}Loading`] = false

      const rawData = res.data
      const list = this[`${prefixTableName}List`]
      const page = this[`${prefixTableName}PageQuery`]
      let H = $(event.target).scrollTop()
      rawData.list.forEach(row => {
        this[`${prefixTableName}List`].push(row)
      })
      $(event.target).scrollTop(H - 50)
      // page.current = Number(rawData.current) / page.size
      this[`${prefixTableName}PageQuery`].current++;
      this[`${prefixTableName}Loading`] = false
      if ((page.current + 1) * page.size >= rawData.total) {
        this[`${prefixTableName}Complete`] = true
      }
    })
  }

  methods[`${prefixTableName}SortInitList`] = function ({prop, order}) {
    this[`${prefixTableName}SortQuery`].asc = order == 'ascending' ? true : order == 'descending' ? false : null
    this[`${prefixTableName}SortQuery`].column = prop
    // let arr = [{
    //   column: prop,
    //   asc: order == 'ascending' ? true : order == 'desc' ? false : null
    // }];
    // this[`${prefixTableName}SortQuery`].orders = JSON.stringify(arr)
    this[`${prefixTableName}GetInitList`]()
  }

  methods[`${prefixTableName}FilterInitList`] = function (filter) {
    this[`${prefixTableName}FilterQuery`] = {...this[`${prefixTableName}FilterQuery`], ...filter}
    this[`${prefixTableName}GetInitList`]()
  }

  methods[`${prefixTableName}Saved`] = function () {
    this[`${prefixTableName}GetInitList`]()
  }

  methods[`${prefixTableName}SelectRow`] = function (row) {
    this[`${prefixTableName}SelectedRow`] = row
    this[`${prefixTableName}SelectedRowId`] = row.id
    const pkName = this[`${prefixTableName}Pk`]
    if (pkName) {
      this[`${prefixTableName}SelectedRowPk`] = row[pkName]
    }
    this[`${prefixTableName}AfterSelectRow`](row)

    this.$refs[prefixTableName].$children[0].toggleRowSelection([{row}])
  }

  methods[`${prefixTableName}SelectRows`] = function (rows) {
    this[`${prefixTableName}SelectedRows`] = rows
    this[`${prefixTableName}SelectedRowIds`] = rows.map(row => row.id)
  }

  methods[`${prefixTableName}UnSelectRow`] = function () {
    this[`${prefixTableName}SelectedRow`] = null
    this[`${prefixTableName}SelectedRowId`] = ''
    const pkName = this[`${prefixTableName}Pk`]
    if (pkName) {
      this[`${prefixTableName}SelectedRowPk`] = ''
    }
  }

  methods[`${prefixTableName}AfterSelectRow`] = function (row) {
  }

  methods[`${prefixTableName}Add`] = function (path) {
    if (isString(path)) {
      this.$router.push(path)
    } else {
      this[`${prefixTableName}OpenAdder`]()
    }
  }

  methods[`${prefixTableName}Edit`] = function (path) {
    if (path) {
      this.$router.push(path)
    } else {
      this[`${prefixTableName}OpenAdder`]('edit')
    }
  }

  methods[`${prefixTableName}Del`] = function (path) {
    if (isString(path)) {
      this.$router.push(path)
    } else {
      this.$confirm('确定删除吗？', '删除').then(() => {
        const parentName = this[`${prefixTableName}Parent`]
        const query = {}
        let id
        if (this[`${prefixTableName}Pk`]) {
          // const parentPkValue = this[`${parentName}SelectedRowPk`]
          // const pkName = this[`${prefixTableName}Pk`]
          const pkValue = this[`${prefixTableName}SelectedRowPk`]
          // query[`p${pkName}`] = parentPkValue
          id = pkValue
        } else {
          id = this[`${prefixTableName}SelectedRowId`]
          query.pid = this[`${parentName}SelectedRowId`]
        }
        this[`${prefixTableName}ApiDel`](id).then(res => {
          this[`${prefixTableName}GetInitList`]()
          if (this[`${prefixTableName}Children`] && this[`${prefixTableName}Children`].length > 0) {
            this[`${prefixTableName}Children`].forEach(child => {
              this[`${child}List`] = []
            })
          }
        })
      }).catch(err => {
      })
    }
  }

  methods[`${prefixTableName}OpenAdder`] = function (mode) {
    this[`${prefixTableName}Adder`].visible = true
    if (mode == 'edit') {
      this[`${prefixTableName}Adder`].mode = mode
    } else {
      this[`${prefixTableName}Adder`].mode = ''
    }
  }

  methods[`${prefixTableName}SetDateRange`] = function (rangeType) {
    let times = []
    switch (rangeType) {
      case '今日':
        times = dateRange.getCurrentDay()
        break
      case '本周':
        times = dateRange.getCurrentWeek()
        break
      case '本月':
        times = dateRange.getCurrentMonth()
        break
      case '全部':
        times = []
        break
      // default:
      //   times = dateRange.getCurrentDay()
    }
    if (times.length) {
      console.log('has')
      this[`${prefixTableName}SearchQuery`].beginSearchTime = times[0].getTime()
      this[`${prefixTableName}SearchQuery`].endSearchTime = times[1].getTime()
    } else {
      console.log('none')
      this[`${prefixTableName}SearchQuery`].beginSearchTime = ''
      this[`${prefixTableName}SearchQuery`].endSearchTime = ''
    }
  }
  methods[`${prefixTableName}SetDateRangeAndSearch`] = function (rangeType) {
    this[`${prefixTableName}SetDateRange`](rangeType)
    this[`${prefixTableName}GetInitList`]()
  }

  return methods
}

function generateTableDatasByArrayString(tables) {
  let data = {tableNames: []}
  tables.forEach(tableName => {
    data = {...data, ...generateTableData(tableName)}
    data.tableNames.push(tableName)
  })
  return data
}

function generateTableMethodsByArrayString(tables) {
  let method = {}
  tables.forEach(tableName => {
    method = {...method, ...generateTableMethod(tableName)}
  })
  return method
}

function generateTableDatasByArrayObject(tables) {
  let data = {tableNames: []}
  tables.forEach(({name: tableName, pk, parent}) => {
    data = {...data, ...generateTableData(tableName, pk, parent)}
    if (parent) {
      if (data[`${parent}Children`]) {
        data[`${parent}Children`].push(tableName)
      } else {
        data[`${parent}Children`] = [tableName]
      }
    }
    data.tableNames.push(tableName)
  })
  return data
}

function generateTableMethodsByArrayObject(tables) {
  let method = {}
  tables.forEach(({name: tableName}) => {
    method = {...method, ...generateTableMethod(tableName)}
  })
  return method
}

function getParamType(param) {
  if (isString(param)) {
    return 'String'
  } else if (isArray(param) && param[0]) {
    const arrParam = param[0]
    if (isString(arrParam)) {
      return 'Array<String>'
    } else if (isObj(arrParam)) {
      return 'Array<Object>'
    }
  }
}

export default function adTable(table) {
  const type = getParamType(table)
  let data = {}
  let methods = {}
  switch (type) {
    case 'String':
      data = {...generateTableData(table), tableNames: [table]}
      methods = generateTableMethod(table)
      break
    case 'Array<String>':
      data = generateTableDatasByArrayString(table)
      methods = generateTableMethodsByArrayString(table)
      break
    case 'Array<Object>':
      data = generateTableDatasByArrayObject(table)
      methods = generateTableMethodsByArrayObject(table)
      break
  }
  return {
    data() {
      return data
    },
    created() {
      this.tableNames.forEach(tableName => {
        this[`${tableName}List`] = []
        this[`${tableName}SearchQuery`] = new SearchQuery()
      })
    },
    methods
  }
}

